home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / GIFLIB12.ARJ / GIFRSIZE.C < prev    next >
C/C++ Source or Header  |  1991-08-05  |  10KB  |  307 lines

  1. /*****************************************************************************
  2. *   "Gif-Lib" - Yet another gif library.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.1, Jul. 1989   *
  5. ******************************************************************************
  6. * Program to resize GIF by given factors horizontally and vertically.         *
  7. * Options:                                     *
  8. * -q : quite printing mode.                             *
  9. * -S x y : scale into size as specified by x and y.                 *
  10. * -s r : resize both x & y direction by factor r.                 *
  11. * -x r : resize the x direction (horizontally) by factor r.             *
  12. * -y r : resize the y direction (vertically) by factor r.             *
  13. * -h : on line help.                                 *
  14. ******************************************************************************
  15. * History:                                     *
  16. * 4 Jul 89 - Version 1.0 by Gershon Elber.                     *
  17. * 22 Dec 89 - Fix minor bag in discarding last line of input (Version 1.1).  *
  18. * 3 Aug 91 - make it scale by an arbitrary size value.                 *
  19. *****************************************************************************/
  20.  
  21. #ifdef __MSDOS__
  22. #include <stdlib.h>
  23. #include <alloc.h>
  24. #endif /* __MSDOS__ */
  25.  
  26. #include <stdio.h>
  27. #include <ctype.h>
  28. #include <string.h>
  29. #include "gif_lib.h"
  30. #include "getarg.h"
  31.  
  32. #define PROGRAM_NAME    "GifRSize"
  33.  
  34. #define MAX_SCALE    16.0              /* Maximum scaling factor. */
  35.  
  36. #ifdef __MSDOS__
  37. extern unsigned int
  38.     _stklen = 16384;                 /* Increase default stack size. */
  39. #endif /* __MSDOS__ */
  40.  
  41. #ifdef SYSV
  42. static char *VersionStr =
  43.         "Gif library module,\t\tGershon Elber\n\
  44.     (C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  45. static char
  46.     *CtrlStr = "GifRSize q%- S%-X|Y!d!d s%-Scale!F x%-XScale!F y%-YScale!F h%- GifFile!*s";
  47. #else
  48. static char
  49.     *VersionStr =
  50.     PROGRAM_NAME
  51.     GIF_LIB_VERSION
  52.     "    Gershon Elber,    "
  53.     __DATE__ ",   " __TIME__ "\n"
  54.     "(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  55. static char
  56.     *CtrlStr =
  57.     PROGRAM_NAME
  58.     " q%- S%-X|Y!d!d s%-Scale!F x%-XScale!F y%-YScale!F h%- GifFile!*s";
  59. #endif /* SYSV */
  60.  
  61. /* Make some variables global, so we could access them faster: */
  62. static GifPixelType
  63.     BackGroundColor = 0;
  64. static double
  65.     XScale = 0.5,
  66.     YScale = 0.5;
  67. static int
  68.     XSize = 0,
  69.     YSize = 0;
  70.  
  71. static void ResizeLine(GifRowType LineIn, GifRowType LineOut,
  72.               int InLineLen, int OutLineLen);
  73. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut);
  74.  
  75. /******************************************************************************
  76. * Interpret the command line and scan the given GIF file.              *
  77. ******************************************************************************/
  78. void main(int argc, char **argv)
  79. {
  80.     int    i, iy, last_iy, l, t, w, h, Error, NumFiles, ExtCode,
  81.     ImageNum = 0,
  82.     SizeFlag = FALSE,
  83.     ScaleFlag = FALSE,
  84.     XScaleFlag = FALSE,
  85.     YScaleFlag = FALSE,
  86.     HelpFlag = FALSE;
  87.     double Scale, y;
  88.     GifRecordType RecordType;
  89.     char s[80];
  90.     GifByteType *Extension;
  91.     GifRowType LineIn, LineOut;
  92.     char **FileName = NULL;
  93.     GifFileType *GifFileIn = NULL, *GifFileOut = NULL;
  94.  
  95.     if ((Error = GAGetArgs(argc, argv, CtrlStr,
  96.         &GifQuitePrint, &SizeFlag, &XSize, &YSize, &ScaleFlag, &Scale,
  97.         &XScaleFlag, &XScale, &YScaleFlag, &YScale,
  98.         &HelpFlag, &NumFiles, &FileName)) != FALSE ||
  99.         (NumFiles > 1 && !HelpFlag)) {
  100.     if (Error)
  101.         GAPrintErrMsg(Error);
  102.     else if (NumFiles > 1)
  103.         GIF_MESSAGE("Error in command line parsing - one GIF file please.");
  104.     GAPrintHowTo(CtrlStr);
  105.     exit(1);
  106.     }
  107.  
  108.     if (HelpFlag) {
  109.     fprintf(stderr, VersionStr);
  110.     GAPrintHowTo(CtrlStr);
  111.     exit(0);
  112.     }
  113.  
  114.     /* If specific direction was set, set other direction to 1: */
  115.     if (!XScaleFlag && YScaleFlag) XScale = 1.0;
  116.     if (!YScaleFlag && XScaleFlag) YScale = 1.0;
  117.  
  118.     /* If the specific direction was not set, but global one did use it: */
  119.     if (!XScaleFlag && ScaleFlag) XScale = Scale;
  120.     if (!YScaleFlag && ScaleFlag) YScale = Scale;
  121.  
  122.     if (XScale > MAX_SCALE) {
  123.     sprintf(s, "XScale too big, maximum scale selected instead (%d).",
  124.                                 MAX_SCALE);
  125.     GIF_MESSAGE(s);
  126.     XScale = MAX_SCALE;
  127.     }
  128.     if (YScale > MAX_SCALE) {
  129.     sprintf(s, "YScale too big, maximum scale selected instead (%d).",
  130.                                 MAX_SCALE);
  131.     GIF_MESSAGE(s);
  132.     YScale = MAX_SCALE;
  133.     }
  134.  
  135.     if (NumFiles == 1) {
  136.     if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL)
  137.         QuitGifError(GifFileIn, GifFileOut);
  138.     }
  139.     else {
  140.     /* Use the stdin instead: */
  141.     if ((GifFileIn = DGifOpenFileHandle(0)) == NULL)
  142.         QuitGifError(GifFileIn, GifFileOut);
  143.     }
  144.     BackGroundColor = GifFileIn -> SBackGroundColor;
  145.  
  146.     /* If size was specified, it is used to derive the scale: */
  147.     if (SizeFlag) {
  148.     XScale = XSize / ((double) GifFileIn -> SWidth);
  149.     YScale = YSize / ((double) GifFileIn -> SHeight);
  150.     }
  151.     else
  152.     {
  153.     XSize = (int) (GifFileIn -> SWidth * XScale + 0.5);
  154.     YSize = (int) (GifFileIn -> SHeight * YScale + 0.5);
  155.     }
  156.  
  157.     /* As at this time we know the Screen size of the input gif file, and as */
  158.     /* all image(s) in file must be less/equal to it, we can allocate the    */
  159.     /* scan lines for the input file, and output file. The number of lines   */
  160.     /* to allocate for each is set by ScaleDown & XScale & YScale:         */
  161.     LineOut = (GifRowType) malloc(XSize * sizeof(GifPixelType));
  162.     LineIn = (GifRowType) malloc(GifFileIn -> SWidth * sizeof(GifPixelType));
  163.  
  164.     /* Open stdout for the output file: */
  165.     if ((GifFileOut = EGifOpenFileHandle(1)) == NULL)
  166.     QuitGifError(GifFileIn, GifFileOut);
  167.  
  168.     /* And dump out its new scaled screen information: */
  169.     if (EGifPutScreenDesc(GifFileOut, XSize, YSize,
  170.     GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor,
  171.     GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == GIF_ERROR)
  172.     QuitGifError(GifFileIn, GifFileOut);
  173.  
  174.     /* Scan the content of the GIF file and load the image(s) in: */
  175.     do {
  176.     if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR)
  177.         QuitGifError(GifFileIn, GifFileOut);
  178.  
  179.     switch (RecordType) {
  180.         case IMAGE_DESC_RECORD_TYPE:
  181.         if (DGifGetImageDesc(GifFileIn) == GIF_ERROR)
  182.             QuitGifError(GifFileIn, GifFileOut);
  183.         /* Put the image descriptor to out file: */
  184.         l = (int) (GifFileIn -> ILeft * XScale + 0.5);
  185.         w = (int) (GifFileIn -> IWidth * XScale + 0.5);
  186.         t = (int) (GifFileIn -> ITop * YScale + 0.5);
  187.         h = (int) (GifFileIn -> IHeight * YScale + 0.5);
  188.         if (l < 0) l = 0;
  189.         if (t < 0) t = 0;
  190.         if (l + w > XSize) w = XSize - l;
  191.         if (t + h > YSize) h = YSize - t;
  192.  
  193.         if (EGifPutImageDesc(GifFileOut, l, t, w, h,
  194.             GifFileIn -> IInterlace, GifFileIn -> IBitsPerPixel,
  195.             GifFileIn -> IColorMap) == GIF_ERROR)
  196.             QuitGifError(GifFileIn, GifFileOut);
  197.  
  198.         if (GifFileIn -> IInterlace) {
  199.             GIF_EXIT("Cannt resize interlaced images - use GifInter first.");
  200.         }
  201.         else {
  202.             GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]:     ",
  203.             PROGRAM_NAME, ++ImageNum,
  204.             GifFileOut -> ILeft, GifFileOut -> ITop,
  205.             GifFileOut -> IWidth, GifFileOut -> IHeight);
  206.  
  207.             for (i = GifFileIn -> IHeight, y = 0.0, last_iy = -1;
  208.              i-- > 0;
  209.              y += YScale) {
  210.             if (DGifGetLine(GifFileIn, LineIn,
  211.                     GifFileIn -> IWidth) == GIF_ERROR)
  212.                 QuitGifError(GifFileIn, GifFileOut);
  213.  
  214.             iy = (int) y;
  215.             if (last_iy < iy && last_iy < YSize) {
  216.                 ResizeLine(LineIn, LineOut,
  217.                        GifFileIn -> IWidth, GifFileOut -> IWidth);
  218.  
  219.                 for (;
  220.                  last_iy < iy && last_iy < GifFileOut -> IHeight - 1;
  221.                  last_iy++) {
  222.                 GifQprintf("\b\b\b\b%-4d", last_iy + 1);
  223.                 if (EGifPutLine(GifFileOut, LineOut,
  224.                         GifFileOut -> IWidth) ==
  225.                                     GIF_ERROR)
  226.                     QuitGifError(GifFileIn, GifFileOut);
  227.                 }
  228.             }
  229.             }
  230.  
  231.             /* If scale is not dividable - dump last lines: */
  232.             while (++last_iy < GifFileOut -> IHeight) {
  233.             GifQprintf("\b\b\b\b%-4d", last_iy);
  234.             if (EGifPutLine(GifFileOut, LineOut,
  235.                     GifFileOut -> IWidth) == GIF_ERROR)
  236.                 QuitGifError(GifFileIn, GifFileOut);
  237.             }
  238.         }
  239.         break;
  240.         case EXTENSION_RECORD_TYPE:
  241.         /* Skip any extension blocks in file: */
  242.         if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR)
  243.             QuitGifError(GifFileIn, GifFileOut);
  244.         if (EGifPutExtension(GifFileOut, ExtCode, Extension[0],
  245.                             Extension) == GIF_ERROR)
  246.             QuitGifError(GifFileIn, GifFileOut);
  247.  
  248.         /* No support to more than one extension blocks, so discard: */
  249.         while (Extension != NULL) {
  250.             if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR)
  251.             QuitGifError(GifFileIn, GifFileOut);
  252.         }
  253.         break;
  254.         case TERMINATE_RECORD_TYPE:
  255.         break;
  256.         default:            /* Should be traps by DGifGetRecordType. */
  257.         break;
  258.     }
  259.     }
  260.     while (RecordType != TERMINATE_RECORD_TYPE);
  261.  
  262.     if (DGifCloseFile(GifFileIn) == GIF_ERROR)
  263.     QuitGifError(GifFileIn, GifFileOut);
  264.     if (EGifCloseFile(GifFileOut) == GIF_ERROR)
  265.     QuitGifError(GifFileIn, GifFileOut);
  266.  
  267.     free(LineOut);
  268.     free(LineIn);
  269. }
  270.  
  271. /******************************************************************************
  272. * Line resizing routine - scale given lines as follows:                  *
  273. * Scale (by pixel duplication/elimination) from InLineLen to OutLineLen.      *
  274. ******************************************************************************/
  275. static void ResizeLine(GifRowType LineIn, GifRowType LineOut,
  276.               int InLineLen, int OutLineLen)
  277. {
  278.     int i, ix, last_ix;
  279.     double x;
  280.  
  281.     OutLineLen--;
  282.  
  283.     for (i = InLineLen, x = 0.0, last_ix = -1;
  284.      i-- > 0;
  285.      x += XScale, LineIn++)
  286.     {
  287.     ix = (int) x;
  288.         for (; last_ix < ix && last_ix < OutLineLen; last_ix++)
  289.         *LineOut++ = *LineIn;
  290.     }
  291.  
  292.     /* Make sure the line is complete. */
  293.     for (LineIn--; last_ix < OutLineLen; last_ix++)
  294.     *LineOut++ = *LineIn;
  295. }
  296.  
  297. /******************************************************************************
  298. * Close both input and output file (if open), and exit.                  *
  299. ******************************************************************************/
  300. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut)
  301. {
  302.     PrintGifError();
  303.     if (GifFileIn != NULL) DGifCloseFile(GifFileIn);
  304.     if (GifFileOut != NULL) EGifCloseFile(GifFileOut);
  305.     exit(1);
  306. }
  307.